using System;
using Habazie.kf2.Core;
using Habazie.kf2.Exposition;

namespace Habazie.kf2.GUI
{
	
	
	public class TabContainer : Gtk.Notebook
	{
		static TabContainer m_Last = null;
		
		private bool m_AutoHideTabs = true;
		
		public static TabContainer Last {
			get { return m_Last; }
		}
		
		static TabContainer ()
		{
	//		Gtk.Notebook.WindowCreationHook = CreateNewWindow; 
		}
		
		
		
		
		/// <summary>
		/// 	Title has changed 	
		/// </summary>
		public event EventHandler TitleChanged = null;
		
		public TabContainer(bool special) : base ()
		{
			this.TabPos = Gtk.PositionType.Bottom;
			Scrollable = true;

			if (! special)
				m_Last = this;
			
			PageAdded += ReconfigureTabs;
			PageRemoved += ReconfigureTabs;
			PageAdded += PageAddedCb;
			PageRemoved += PageRemovedCb;
			
			GroupId = 0x63686174;
		}
		
		
		public SubWindow Current {
			get { return this.CurrentPageWidget as SubWindow; }
		}
		
		
		/// <summary>
		/// 	Active SubWindow title 	
		/// </summary>
		public string Title {
			get {
				SubWindow win = Current;
				if (win.NumEvents == 0)
					return win.Title;
				else
					return String.Format ("* {0} ({1})", win.Title, win.NumEvents);
			}
		}
		
		/// <summary>
		/// 	Auto Hide tabs
		/// </summary>
		public bool AutoHideTabs {
			get { return m_AutoHideTabs; }
			set { m_AutoHideTabs = value; }
		}
		
		/// <summary>
		/// 	Add a sub window 	
		/// </summary>
		public void AddChild (SubWindow child)
		{
			TabLabel label = new TabLabel (child);
			this.AppendPage (child, label);
			SetTabReorderable (child, true);
			SetTabDetachable (child, child.IsDetachable ());
			UpdateTabLabel (child, label);
			
			
			if (TitleChanged != null)
				TitleChanged (this, new EventArgs ());
		}
		
		
		/// <summary>
		/// 	Remove a child window 	
		/// </summary>
		public void RemoveChild (SubWindow child)
		{
			if (TitleChanged != null)
				TitleChanged (this, new EventArgs ());
		}
		
		
		public void NotifyStateEvent ()
		{
			if (Current != null)
				Current.NotifyStateEvent ();
		}
		
		
		/// <summary>
		/// 	Check whether a child is active 	
		/// </summary>
		public bool IsActiveChild (SubWindow child)
		{
			Gtk.Window win = this.Toplevel as Gtk.Window;
			if (win == null) return false;
			
			if (! win.IsActive)
				return false;
				
//			Util.Debug ("gui", "Current={0}, Child={1}", CurrentPage, PageNum (child));
			return CurrentPage == PageNum (child);
		}
		
		/* Event handlers */
		protected virtual void ReconfigureTabs (object sender, EventArgs args)
		{
			bool show_tabs = (! m_AutoHideTabs || this.NPages != 1);
			this.ShowBorder = false;
			this.ShowTabs = show_tabs;
		}
		
		
		
		/// <summary>
		/// 	Child title has changed 	
		/// </summary>
		protected virtual void ChildTitleChanged (object sender, EventArgs args)
		{
			SubWindow win = (SubWindow) sender;
			
			TabLabel label = (TabLabel) GetTabLabel (win);
			UpdateTabLabel (win, label);
			
//			if (PageNum (win) == CurrentPage && TitleChanged != null)
			if (TitleChanged != null)
				TitleChanged (this, new EventArgs ());
		}
		
		
		private void UpdateTabLabel (SubWindow win, TabLabel label)
		{
			string title = (win.ShortTitle != null) ? win.ShortTitle : win.Title;
			label.Text = (win.NumEvents > 0) ? String.Format ("{0} ({1})", title, win.NumEvents) : win.Title;
			label.Pixbuf = win.Icon;
		}
		
		protected override void OnChangeCurrentPage (int offset)
		{
//			Util.Debug ("OnChangeCurrentPage ({0})", offset);
			base.OnChangeCurrentPage (offset);
			
			if (TitleChanged != null)
				TitleChanged (this, new EventArgs ());
		}
		
		
		// FIXME: these methods break every Gtk.Notebook in application:/
//		protected override void OnPageAdded (Gtk.Widget p0, uint p1)
//		{
//			base.OnPageAdded (p0, p1);
//			
//			SubWindow win = p0 as SubWindow;
//			if (win != null) {
//				win.TitleChanged += ChildTitleChanged;
//			}
//		}
//		
//		
//		protected override void OnPageRemoved (Gtk.Widget p0, uint p1)
//		{
//			base.OnPageRemoved (p0, p1);
//
//			SubWindow win = p0 as SubWindow;
//			if (win != null) {
//				win.TitleChanged -= ChildTitleChanged;
//			}
//		}
//

		protected virtual void PageAddedCb (object sender, Gtk.PageAddedArgs args)
		{
			SubWindow win = args.P0 as SubWindow;
			if (win != null) {
				win.TitleChanged += ChildTitleChanged;
				win.RequestEvent += HandleRequest;
			}
		}
		

		protected virtual void PageRemovedCb (object sender, Gtk.PageRemovedArgs args)
		{
			SubWindow win = args.P0 as SubWindow;
			if (win != null) {
				win.TitleChanged -= ChildTitleChanged;
				win.RequestEvent -= HandleRequest;
			}
		}


		protected override void OnSwitchPage (Gtk.NotebookPage page, uint page_num)
		{
//			Util.Debug ("gui", "OnSwitchPage ({0}); CurrentPage={1}", page_num, CurrentPage);
			SubWindow former = CurrentPageWidget as SubWindow;
			base.OnSwitchPage (page, page_num);
			SubWindow current = GetNthPage ((int)page_num) as SubWindow;
			
			if (former != null)	 former.NotifyStateEvent (); 
			if (current != null) current.NotifyStateEvent ();
			
			
			if (TitleChanged != null)
				TitleChanged (this, new EventArgs ());
		}
		
		protected override bool OnDestroyEvent (Gdk.Event e)
		{
			m_Last = null; // FIXME: organize it as a stack
			return base.OnDestroyEvent (e);
		}

	
		protected virtual void HandleRequest (object o, string request)
		{
			SubWindow w = o as SubWindow;
			if (o == null)
				return;

			switch (request) {
				case "raise":
					Gtk.Window win = this.Toplevel as Gtk.Window;
					win.GdkWindow.Raise ();
					w.GrabFocus ();
					break;
			}
		}

		
		/// <summary>
		/// 	Tab label widget 	
		/// </summary>
		internal class TabLabel : Gtk.EventBox
		{
			private SubWindow m_Window;
			private Gtk.Image m_Image;
			private Gtk.Label m_Label;
			private Gtk.Button m_Button;
			
			public TabLabel (SubWindow win) : base ()
			{
				Gtk.HBox hbox = new Gtk.HBox (false, 6);
				
				m_Window = win;
				m_Image = new Gtk.Image ();
				m_Image.Show ();
				
				m_Label = new Gtk.Label ();
				m_Label.Show ();
				
				m_Button = new XButton ();
				Gtk.Image img = new Gtk.Image ("gtk-close", Gtk.IconSize.Menu);
				img.Show ();
				m_Button.Add (img);
				m_Button.Relief = Gtk.ReliefStyle.None;
				m_Button.Clicked += CloseButtonClicked;
				m_Button.Show ();
				
				hbox.PackStart (m_Image, false, false, 0);
				hbox.PackStart (m_Label, true,true, 0);
				hbox.PackEnd (m_Button, false, false, 0);
				
				hbox.Show ();
				this.Add (hbox);
		//		this.PackEnd (img, false, false, 0);
			}
			
			public string Text {
				get { return m_Label.Text; }
				set { m_Label.Text = value; } 
			}
			
			public Gdk.Pixbuf Pixbuf {
				get { return m_Image.Pixbuf; }
				set { m_Image.Pixbuf = value; }
			}
			
			private void CloseButtonClicked (object sender, EventArgs args)
			{
				m_Window.Delete ();
			}

			protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
			{
				if (evnt.Button == 3) {
					Gtk.Menu menu = new Gtk.Menu ();
					
					menu.Append (new Gtk.MenuItem ("Detach tab"));
					menu.Append (new Gtk.MenuItem ("Close tab"));
					menu.ShowAll ();
					
					menu.Popup (null, null, PositionMenu, evnt.Button, evnt.Time);
					return true;
				} else {
					return base.OnButtonPressEvent (evnt);
				}
			}
			protected virtual void PositionMenu (Gtk.Menu menu, out int x, out int y, out bool push_in)
			{
				int wx, wy;
				int width, height;
				Gtk.Widget w = this;
				w.GdkWindow.GetOrigin (out wx, out wy);
				w.GdkWindow.GetSize (out width, out height);
				
				x = wx;
				y = wy + height;
				push_in = true;
			}
		}
	}
}
